package cn.schoolwow.quickflow.domain;

import cn.schoolwow.quickflow.QuickFlowExecutor;
import cn.schoolwow.quickflow.flow.BusinessFlow;
import cn.schoolwow.quickflow.listener.SingleFlowListener;
import cn.schoolwow.quickflow.listener.TryCatchFinallyHandler;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class FlowExecutorConfig {
    /**
     * 流程名称
     */
    public String name;

    /**
     * 流程名称
     */
    public String currentFlowName;

    /**
     * 流程上下文对象
     */
    public FlowContext flowContext;

    /**
     * 是否打印流程列表
     */
    public Boolean printTrace;

    /**
     * 是否忽略中断
     */
    public Boolean ignoreBroken;

    /**
     * 是否忽略异常
     */
    public Boolean ignoreException;

    /**
     * 当前流程
     * */
    public BusinessFlow currentFlow;

    /**
     * 业务流程列表
     */
    public List<BusinessFlow> flowList = new ArrayList<>();

    /**
     * 当前流程数据
     */
    public Map<String,Object> currentFlowDataMap = new ConcurrentHashMap<>();

    /**
     * 当前复合流程数据
     */
    public Map<String,Object> currentCompositeFlowDataMap = new ConcurrentHashMap<>();

    /**
     * 流程执行前后处理事件监听
     */
    public SingleFlowListener singleFlowListener;

    /**
     * try-catch-finally事件处理
     */
    public TryCatchFinallyHandler tryCatchFinallyHandler;

    /**
     * 上级流程配置
     */
    public FlowExecutorConfig parentFlowExecutorConfig;

    /**
     * 主流程配置
     */
    public FlowExecutorRootConfig flowExecutorRootConfig;

    /**
     * 执行器对象
     */
    public QuickFlowExecutor quickFlowExecutor;

    /**
     * 是否为复合流程
     * */
    public boolean compositeBusiness;

    /**是否需要打印流程日志*/
    public boolean shouldPrintTrace(){
        if(flowExecutorRootConfig.flowConfig.flowConfigSwitcherContext.debug){
            return true;
        }
        Boolean shouldPrintTrace = this.printTrace;
        if(null==shouldPrintTrace){
            if(flowExecutorRootConfig.flowConfig.flowConfigSwitcherContext.printTrace){
                //判断层级
                Integer flowLevel = getFlowLevel();
                if(flowLevel<=flowExecutorRootConfig.flowConfig.flowConfigSwitcherContext.traceLevel){
                    shouldPrintTrace = true;
                }else{
                    shouldPrintTrace = false;
                }
            }else{
                shouldPrintTrace = false;
            }
        }
        return shouldPrintTrace;
    }

    /**
     * 打印流程内容
     */
    public void printFlowTrace(String content) {
        boolean shouldPrintTrace = shouldPrintTrace();

        if (shouldPrintTrace) {
            printTrace(content);
        }
    }

    /**
     * 打印流程内容
     */
    public void printFlowTraceWithIndex(String content) {
        boolean shouldPrintTrace = shouldPrintTrace();
        if (shouldPrintTrace) {
            content = "[" + (flowExecutorRootConfig.index.getAndIncrement()) + "]"+content;
            printTrace(content);
        }
    }

    /**
     * 获取备注记录
     * */
    public StringBuilder getRemarkBuilder(){
        StringBuilder remarkBuilder = flowExecutorRootConfig.remarkBuilderThreadLocal.get();
        if(null==remarkBuilder){
            flowExecutorRootConfig.remarkBuilderThreadLocal.set(new StringBuilder());
        }
        return flowExecutorRootConfig.remarkBuilderThreadLocal.get();
    }

    /**
     * 记录日志
     * */
    public void recordContent(String content){
        if(flowExecutorRootConfig.startRecord){
            flowExecutorRootConfig.recordBuilder.append("["+ name +"]"+content+"\r\n");
        }
    }

    private void printTrace(String content){
        Integer flowLevel = getFlowLevel();
        for (int i = 0; i < flowLevel; i++) {
            flowExecutorRootConfig.printTraceBuilder.append("\t");
        }
        flowExecutorRootConfig.printTraceBuilder.append(content + "\r\n");
        if(flowExecutorRootConfig.flowConfig.flowConfigSwitcherContext.debug){
            StringBuilder builder = new StringBuilder();
            for (int i = 0; i < flowLevel; i++) {
                builder.append("\t");
            }
            builder.append("【"+flowLevel+"】"+content);
            System.out.println(builder.toString());
        }
    }

    public Integer getFlowLevel(){
        Integer flowLevel = flowExecutorRootConfig.flowLevel.get();
        if(null==flowLevel){
            flowLevel = 0;
            flowExecutorRootConfig.flowLevel.set(flowLevel);
        }
        return flowLevel;
    }
}